
#include <assert.h>
#include <string.h>

#include "resource.h"
#include "buffer.h"

//class TextResourceChecker
TextResourceChecker TextResourceChecker :: m_obj;

//static
int TextResourceChecker :: Config( string * texttypes, int size )
{
	if ( texttypes != NULL  && size > 0 )
		return m_obj.Init( texttypes, size);
	else
		return -1;
}	

bool TextResourceChecker :: IsTextResource( string type )
{
	return m_obj.IsTextType( type );
}
//not static

TextResourceChecker :: TextResourceChecker()
{
	m_textTypes = NULL;
	m_textTypesSize = 0;
}

TextResourceChecker :: ~TextResourceChecker()
{
	if ( NULL != m_textTypes )
	{
		delete []m_textTypes;
		m_textTypes = NULL;
	}
}

int TextResourceChecker :: Init( string * texttypes, int size )
{
	m_textTypes = new string[size];
	for ( int i=0; i<size; i++)
	{
		m_textTypes[i] = texttypes[i];
	}
	m_textTypesSize = size;
	return 0;
}

bool TextResourceChecker :: IsTextType( string type )
{
	if ( m_textTypes == NULL )
		return  false;

	for ( int i=0; i<m_textTypesSize; ++i )
	{
		if ( m_textTypes[i] == type )
			return true;
	}
	return false;
}
//class ResourceItem

ResourceItem :: ResourceItem( const string type, char * buf, int buflen)
{
	assert( buf != NULL );
	assert( buflen >= 0 );
	m_strType = type;
	m_ptBuffer = new Buffer( buflen + 1 );// if is text type, it is necessuary to add '\0'
	m_ptBuffer->Append( buf, buflen );
	if ( TextResourceChecker::IsTextResource( type ) )
	{
		//m_ptBuffer->Append('\0');
	}
}

ResourceItem ::  ~ResourceItem()
{
	if ( NULL != m_ptBuffer )
		delete m_ptBuffer;
}

int ResourceItem :: GetLength()
{
	return m_ptBuffer->GetLimit();
}

Buffer * ResourceItem :: GetBuffer()
{
	return m_ptBuffer;
}

string ResourceItem :: GetType()
{
	return m_strType;
}

//class Resource

ResourceMap * Resource :: m_ptMap;

int Resource :: Config( const char * psDirpath )
{
	m_ptMap = new ResourceMap( psDirpath );
	if ( NULL != m_ptMap )
		return 0;
	else
		return -1;
}

int Resource :: DestroyResource()
{
	if ( NULL != m_ptMap )
	{
		delete m_ptMap;
	}
	return 0;
}

ResourceItem * Resource ::  GetResource( const char * path )
{
	string strpath = path;
	return m_ptMap->GetResource( &strpath );
}

ResourceItem * Resource :: GetResource( const string * path )
{
	return m_ptMap->GetResource( path );
}


//class ResourceMap

ResourceMap :: ResourceMap( const char * psDirpath )
{
	m_strDirpath = psDirpath;
}

ResourceMap :: ~ResourceMap()
{
}

ResourceItem * ResourceMap :: GetResource( const string * path )
{
	ResourceItem * result = NULL;
	if ( NULL != path )
	{
		//try get resource from cache[map], if NULL try to find it in the disk
		map<string, ResourceItem*>::iterator it = m_map.find( *path );
		if ( it != m_map.end() )//find it in cache[map]
		{
			result = it->second;
		}
		else//try to find it in the disk
		{
			string path2 = m_strDirpath;
			path2.append( *path );
			
			FILE * fp = fopen( path2.c_str(), "r" );
			if ( NULL != fp )
			{
				string::size_type pos = path2.rfind('.');
				string type;
				
				if ( string::npos != pos && pos + 1 < path2.length() ) // have type
				{
					type = path2.substr( pos+1 );
				}
				else// no type
				{
					type = "unknow";
				}
					
				if ( 0 == fseek( fp, 0, SEEK_END ) )
				{
					int len = ftell( fp );
					char * buf = new char[len];
					memset( buf, 0, len );
					
					fseek( fp, 0, SEEK_SET );
					int ret = fread( buf, 1, len, fp );
				
					if ( len == ret )
					{
						ResourceItem * ptResourceItem = new ResourceItem( type, buf, len );
						m_map.insert( pair<string, ResourceItem*> ( *path, ptResourceItem ) );
						result = ptResourceItem;
					}
					delete []buf;
				}
				fclose( fp );
			}
		}
	}
	return result;
}
